package com.example.capsule_netty.global;

import com.example.capsule_netty.bean.MessageBean;
import com.example.capsule_netty.bean.UserInfoBean;
import com.example.capsule_netty.impl.MessageActionImpl;
import com.example.capsule_netty.mapper.UserInfoMapper;
import com.example.capsule_netty.protocol.MessageBeanProtocol;
import com.google.gson.Gson;
import io.netty.channel.Channel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * @Author: zhuzhiming
 * @Date: 2022/4/27 20:00
 */
@Component
public class UserAndChannelRelevance {

    @Autowired
    MessageActionImpl messageActionImpl;

    @Autowired
    RedisTemplate<String, String> redisTemplate;

    @Resource
    UserInfoMapper userInfoMapper;

    private static final MultiValueMap<String, Map<String, Channel>> roomUserChannelMap = new LinkedMultiValueMap<>(); //userId
    private static final Map<String, Channel> userToChannel = new HashMap<>(); //imei 全局的
    private static final Map<Channel, String> channelToRoomMap = new HashMap<>();//roomName
    private static final Map<Channel, String> channelToUserMap = new HashMap<>(); //userId

    public synchronized void putFromRoom(String roomNam, String userId, Channel channel) {
        Map<String, Channel> map = new HashMap<>();
        map.put(userId, channel);
        List<Map<String, Channel>> list = roomUserChannelMap.get(roomNam);
        if (list == null) {
            list = new ArrayList<>();
        }
        list.add(map);
        channelToUserMap.put(channel, userId);
        channelToRoomMap.put(channel, roomNam);
        roomUserChannelMap.put(roomNam, list);
    }


    public synchronized void putFromImei(String imei, Channel channel) {
        userToChannel.put(imei, channel);
    }

    public Channel getChannelFromImei(String imei) {
        return userToChannel.get(imei);
    }

    public Channel getChannel(String roomNam, String userId) {

        List<Map<String, Channel>> mapList = roomUserChannelMap.get(roomNam);
        for (Map<String, Channel> channelMap : mapList) {
            if (channelMap.containsKey(userId)) {
                return channelMap.get(userId);
            }
        }
        return null;
    }


    public boolean removeByRoomAndUserUniqueMark(String roomNam, String userId) {

        List<Map<String, Channel>> mapList = roomUserChannelMap.get(roomNam);
        if (mapList != null) {
            for (Map<String, Channel> channelMap : mapList) {
                Channel channel = channelMap.remove(userId);
                if (channel != null) {
                    return true;
                }
            }
        }
        return false;
    }

    public void removeByChannel(Channel channel) {
        String roomNam = channelToRoomMap.remove(channel);
        String userId = channelToUserMap.remove(channel);

        if (roomNam != null && !roomNam.equals("") && userId != null && !userId.equals("")) {
            boolean needToSub = removeByRoomAndUserUniqueMark(roomNam, userId);
            if (needToSub) {
                doSendRoomPeopleCountChangeMessage(channel, roomNam, userId, -1);
            }
        }
    }



    public HashSet<Channel> getChannels(String roomNam) {

        HashSet<Channel> set = new HashSet<>();
        if (roomNam != null && !roomNam.equals("")) {
            List<Map<String, Channel>> mapList = roomUserChannelMap.get(roomNam);
            for (Map<String, Channel> channelMap : mapList) {
                for (String key : channelMap.keySet()) {
                    set.add(channelMap.get(key));
                }
            }
        }
        return set;
    }


    public void removeUserFromServer(String imei) {
        Channel channel = userToChannel.get(imei);
        userToChannel.remove(imei);

        if (channel == null) return;

        removeByChannel(channel);

    }


    public List<String> doGetChatRoomFriend(String roomName) {

        List<Map<String, Channel>> mapList = roomUserChannelMap.get(roomName);
        Set<String> set = new HashSet<>();
        for (Map<String, Channel> channelMap : mapList) {
            set.addAll(channelMap.keySet());
        }
        List<String> userIdList = new ArrayList<>(set);
        return userIdList;
    }

    private void doSendRoomPeopleCountChangeMessage(Channel channel, String roomName, String userId, int count) {
        MessageBean messageBean = new MessageBean();
        String userJson = redisTemplate.opsForValue().get(userId);
        UserInfoBean userInfoBean = null;
        if (!StringUtils.hasLength(userJson)) {
            userInfoBean = userInfoMapper.selectById(userId);
            redisTemplate.opsForValue().set(userId, new Gson().toJson(userInfoBean),10, TimeUnit.MINUTES);
        } else {
            userInfoBean = new Gson().fromJson(userJson, UserInfoBean.class);
        }
        messageBean.setSenderName(userInfoBean.getNickname());
        messageBean.setRoomName(roomName);
        messageBean.setMsgType(7);
        messageBean.setSenderId(userId);
        messageBean.setContent("");
        messageBean.setPeopleChangeCount(count);
        messageBean.setOneToOne(false);
        messageActionImpl.dealChatAction(channel, messageBean);
    }

    public void doAddRoomPeopleCount(String roomName, String imei) {
        Channel channel = userToChannel.get(imei);
        String userId = channelToUserMap.get(channel);
        doSendRoomPeopleCountChangeMessage(channel, roomName, userId, 1);
    }

    public int getOnlineStatus(String imei) {

        return userToChannel.get(imei) == null ? 0 : 1;

    }





}
